package com.training.bt.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.training.bt.common.PageResponseDTO;
import com.training.bt.entity.Resource;
import com.training.bt.entity.User;
import com.training.bt.mapper.ResourceMapper;
import com.training.bt.mapper.ResourceTagMapper;
import com.training.bt.mapper.UserMapper;
import com.training.bt.mapper.UserTagMapper;
import com.training.bt.resource.dto.ResourceListItemDTO;
import com.training.bt.security.util.SecurityUtils;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class RecommendationService {
    private final UserMapper userMapper;
    private final UserTagMapper userTagMapper;
    private final ResourceTagMapper resourceTagMapper;
    private final ResourceMapper resourceMapper;

    public PageResponseDTO<ResourceListItemDTO> calculateRecommendations(int page, int size) {
        Page<Resource> pageRequest = new Page<>(page, size);
        // 系统是会员制，用户必须登录，所以这里不需要检查null
        User user = SecurityUtils.getCurrentUser();
        Long userId = user.getId();
        List<Long> tagIds = userTagMapper.findTagidByUser(userId);

        if (tagIds.isEmpty()) {
            // 用户没有标签，返回热门推荐
            return getPopularRecommendations(pageRequest);
        }

        PageResponseDTO<ResourceListItemDTO> personalized = getCustomPagedRecommendations(pageRequest, userId, tagIds);

        // 混合推荐：当个性化结果不足时补充热门资源
        int minResults = size;
        if (personalized.getRecords() != null && personalized.getRecords().size() < minResults) {
            int needed = minResults - personalized.getRecords().size();
            PageResponseDTO<ResourceListItemDTO> popular = getPopularRecommendations(
                    new Page<>(1, needed));

            List<ResourceListItemDTO> combined = new ArrayList<>(personalized.getRecords());
            combined.addAll(popular.getRecords());

            // 去重
            Set<Long> existingIds = new HashSet<>();
            List<ResourceListItemDTO> uniqueCombined = combined.stream()
                    .filter(item -> existingIds.add(item.getId()))
                    .collect(Collectors.toList());

            // 确保不超过请求的数量
            if (uniqueCombined.size() > size) {
                uniqueCombined = uniqueCombined.subList(0, size);
            }

            // 注意：总记录数这里不能简单相加，因为去重后数量可能变化
            // 我们返回个性化推荐的总数，因为补充的热门资源只是临时措施
            return new PageResponseDTO<>(personalized.getTotal(), uniqueCombined);
        }

        return personalized;
    }

    private PageResponseDTO<ResourceListItemDTO> getCustomPagedRecommendations(
            Page<Resource> pageRequest,
            Long userId,
            List<Long> tagIds) {

        // 计算分页偏移量
        long offset = (pageRequest.getCurrent() - 1) * pageRequest.getSize();
        long pageSize = pageRequest.getSize();

        // 使用正确的分页参数
        List<Long> resourceIds = resourceTagMapper.selectPagedRecommendationIds(
                offset,
                pageSize,
                userId,
                tagIds);

        if (resourceIds.isEmpty()) {
            return new PageResponseDTO<>(0L, null);
        }

        // 添加总记录数查询
        Long total = resourceTagMapper.countRecommendations(userId, tagIds);

        // 批量查询资源详情（保持原始ID顺序）
        Map<Long, Resource> resourceMap = resourceMapper.selectBatchIds(resourceIds).stream()
                .collect(Collectors.toMap(Resource::getId, Function.identity()));

        // 获取所有上传者ID
        Set<Long> uploaderIds = resourceMap.values().stream()
                .map(Resource::getUploader)
                .collect(Collectors.toSet());

        // 批量查询用户信息
        Map<Long, User> userMap = userMapper.selectBatchIds(uploaderIds).stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        List<ResourceListItemDTO> dtoList = resourceIds.stream()
                .map(resourceMap::get)
                .filter(Objects::nonNull)
                .map(resource -> {
                    ResourceListItemDTO dto = new ResourceListItemDTO();
                    dto.setId(resource.getId());
                    dto.setTitle(resource.getTitle());
                    dto.setDescription(resource.getDescription());
                    dto.setUploadTime(resource.getUploadTime());
                    dto.setCoverImageUrl(resource.getCoverImageUrl());

                    // 设置上传者信息
                    User user = userMap.get(resource.getUploader());
                    if (user != null) {
                        dto.setUploaderName(user.getUsername());
                    } else {
                        dto.setUploaderName("未知用户");
                    }
                    return dto;
                }).toList();

        return new PageResponseDTO<>(total, dtoList);
    }

    private PageResponseDTO<ResourceListItemDTO> getPopularRecommendations(Page<Resource> pageRequest) {
        LambdaQueryWrapper<Resource> wrapper = new LambdaQueryWrapper<Resource>()
                .eq(Resource::getVisible, true)
                .orderByDesc(Resource::getDownloadCount);

        Page<Resource> result = resourceMapper.selectPage(pageRequest, wrapper);
        return convertToDTO(result);
    }

    private PageResponseDTO<ResourceListItemDTO> convertToDTO(Page<Resource> page) {
        // 一次性获取所有需要的用户ID
        Set<Long> userIds = page.getRecords().stream()
                .map(Resource::getUploader)
                .collect(Collectors.toSet());

        // 批量查询用户信息
        Map<Long, User> userMap = userMapper.selectBatchIds(userIds).stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        List<ResourceListItemDTO> dtoList = page.getRecords().stream().map(resource -> {
            ResourceListItemDTO dto = new ResourceListItemDTO();
            dto.setId(resource.getId());
            dto.setTitle(resource.getTitle());
            dto.setDescription(resource.getDescription());
            dto.setUploadTime(resource.getUploadTime());
            dto.setCoverImageUrl(resource.getCoverImageUrl());

            User user = userMap.get(resource.getUploader());
            if (user != null) {
                dto.setUploaderName(user.getUsername());
            } else {
                dto.setUploaderName("未知用户");
            }
            return dto;
        }).toList();

        return new PageResponseDTO<>(page.getTotal(), dtoList);
    }
}
